﻿#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:6031)

#include<stdio.h>
#include<stdlib.h>

//指针变量和地址
//int main()
//{
// 操作指针指向的空间
	//short b = 20;
	//char c = 'a';
	//double t = 34.5;
	//
	////b
	//short* p1 = &b;//p1指向b
	//printf("%p\n",p1);
	//*p1 = *p1 + 10;//间接改变b的值
	//printf("%hd\n", *p1);
	//printf("%p\n", &b);//查看b的地址

	//printf("\n");
	////c
	//char* p2 = &c;//p2指向c
	//printf("%p\n", p2);
	//*p2 = *p2 + 1;//间接改变c的值
	//printf("%hd\n", *p2);
	//printf("%p\n", &c);//查看c的地址

	//printf("\n");
	////t
	//double* p3 = &t;//p3指向t
	//printf("%p\n", p3);
	//*p3 = *p3 + 1;//间接改变t的值
	//printf("%lf\n", *p3);
	//printf("%p\n", &t);//查看t的地址
//
//}






//int main()
//{
//	//操作指针本身的空间
//	int a = 30;
//	int b = 50;
//
//	int* p = &a;//p指向a
//	printf("%p %d\n",p,*p);
//	 
//	p = &b;//p指向b
//	printf("%p %d", p, *p);
//}
//int main()
//{
//	//指针变量大小  64位 8
//	int* p1;
//	short* p2;
//	char* p3;
//	double* p4;
//	printf("%d %d %d %d", sizeof(p1), sizeof(p2), sizeof(p3), sizeof(p4));
//
//	//指针变量大小  32位 4
//	int* p1;
//	short* p2;
//	char* p3;
//	double* p4;
//	printf("%d %d %d %d", sizeof(p1), sizeof(p2), sizeof(p3), sizeof(p4));
//}
//总结：指针变量占空间的大小与指向对象类型无关





//int main()
//{
//	int a = 30;
//	short b = 20;
//	char c = 'a';
//	double t = 34.5;
//
//	int* p1 = &a;
//	printf("%p\n", p1);
//	//p1 = p1 + 1;
//	p1++;//写操作（地址变化）
//	//p1 + 1;//读操作（地址不变）(p1+1) 地址变化
//	printf("%p\n", p1);
//
//	printf("\n");
//
//	short* p2 = &b;
//	printf("%p\n", p2);
//	//p2 = p2 + 1;
//	p2++;//写操作（地址变化）
//	//p2 + 1;//读操作（地址不变）(p2+1) 地址变化
//	printf("%p\n", p2); printf("\n");
//
//	printf("\n");
//
//	char* p3 = &c;
//	printf("%p\n", p3);
//	//p2 = p2 + 1;
//	p3++;//写操作（地址变化）
//	//p2 + 1;//读操作（地址不变）(p2+1) 地址变化
//	printf("%p\n", p3);
//
//	printf("\n");
//
//	double* p4 = &t;
//	printf("%p\n", p4);
//	//p2 = p2 + 1;
//	p4++;//写操作（地址变化）
//	//p2 + 1;//读操作（地址不变）(p2+1) 地址变化
//	printf("%p\n", p4);
//
//	
//}
//总结：指向对象类型决定了指针向前/向后走“多大的距离”（字节）






//int main()
//{
//	//利用将int a[6]={1,2,3,4,,5,6}翻转
//	int a[6] = { 1,2,3,4,5,6 };
//	int* p = a;
//	int* q = a + 5;
//	for (; p < q; p++, q--)
//	{
//		int temp = *p;
//		*p = *q;
//		*q = temp;
//	}
//	p = a;
//	for (; p <= a + 5; p++)
//	{
//		printf("%d ", *p);
//	}
//
//
//}


//const修饰指针
//int main()
//{
//	
//	//const修饰变量--变量无法修改，但是拿到变量的地址则可以修改
//	/*const int n = 10;
//	printf("%d\n",n);
//	int* p = &n;
//	*p = 0;
//	printf("%d", n);*/
//	//const修饰指针
//	//const在*左边的情况
//	//int n = 10;
//	//int m = 20;
//	//const int* p = &n;
//	//*p = 20;//ok?  no 
//	//p = &m; //ok?  yes
//	//const在*右边的情况
//	//int n = 10;
//	//int m = 20;
//	//int* const p = &n;
//	//*p = 20; //ok? yes
//	//p = &m; //ok?  no
//	//const在*的左右边两边的情况
//	//int n = 10;
//	//int m = 20;
//	//int const* const p = &n;
//	//*p = 20; //ok? no
//	//p = &m; //ok?  no
//	//总结：const如果放在*的左边，修饰的是指针指向的内容，保证指针指向的内容不能通过指针来改变,但是指针变量本⾝的内容可变。
//		  //const如果放在* 的右边，修饰的是指针变量本⾝，保证了指针变量的内容不能修改，但是指针指向的内容，可以通过指针改变。
//		
//}



//指针运算
//int my_strlen(char* s)
//{
//	char* p = s;
//	while (*p != '\0')
//	{
//		p++;//地址偏移1个char
//	}
//	return p - s;
//}
//int main()
//{
	//指针+- 整数   用指针打印数组
	/*int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr1) / sizeof(arr1[0]);
	int* p = arr1;
	for (int i = 0; i < len; i++)
	{
		printf("%d ",*(p+i));
	}*/
	//指针-指针
	/*printf("%d\n", my_strlen("abc"));
	return 0;*/
	//指针的关系运算
	/*int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr1) / sizeof(arr1[0]);
	int* p = arr1;
	for (; p < arr1 + len; p++)
	{
		printf("%d ",*p);
	}*/

//}




//野指针
//int* test()
//{
//	int n = 100;
//	return &n;
//}
//int main()
//{
	//野指针的成因
	//指针未初始化  错误示范
	/*int* p;
	*p = 10;
	printf("%d %p", *p, p);*/
	//指针越界    错误示范
	//int arr[10] = { 0 };
	//int* p = &arr[0];
	//int i = 0;
	//for (i = 0; i <= 11; i++)
	//{
	//	//当指针指向的范围超出数组arr的范围时，p就是野指针
	//	*(p++) = i;
	//}
	//指向空间释放  错误示范   不要返回局部变量的地址
	/*int* p = test();
	printf("%d\n", *p);
	return 0;*/
//}




//使⽤指针访问数组
//int main()
//{
	//(1)
	/*int arr[5];
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (int i = 0; i < sz; i++)
	{
		scanf("%d",p+i);
	}
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p+i));
	}*/
	//(2)
	/*int arr[5];
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (int i = 0; i < sz; i++)
	{
		scanf("%d", &p[i]);
	}
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", p[i]);
	}*/

//}




//一维数组传参的本质
//void test(int* arr)//参数写成指针形式
//{
//	printf("%d\n", sizeof(arr));//计算⼀个指针变量的⼤⼩
//}
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	test(arr);
//	return 0;
//}


//指针数组模拟二维数组   指针数组是⼀种数组，数组中存放的是地址（指针）
//int main()
//{
//	int arr1[] = { 1,2,3,4,5 };
//	int arr2[] = { 2,3,4,5,6 };
//	int arr3[] = { 3,4,5,6,7 };
//	int* p[3] = { arr1,arr2,arr3 };
//	int i, j;
//	for (i = 0; i < 3; i++)
//	{
//		for (j = 0; j < 5; j++)
//		{
//			printf("%d ",p[i][j]);
//		}
//		printf("\n");
//	}
//}


//字符指针
//int main()
//{
//	char str1[] = "hello bit.";
//	char str2[] = "hello bit.";
//	const char* str3 = "hello bit.";
//	const char* str4 = "hello bit.";
//	if (str1 == str2)
//		printf("str1 and str2 are same\n");
//	else
//		printf("str1 and str2 are not same\n");
//
//	if (str3 == str4)
//		printf("str3 and str4 are same\n");
//	else
//		printf("str3 and str4 are not same\n");
//
//	return 0;
//}
//原因：这⾥str3和str4指向的是⼀个同⼀个常量字符串。C/C++会把常量字符串存储到单独的⼀个内存区域，
//当⼏个指针指向同⼀个字符串的时候，他们实际会指向同⼀块内存。但是⽤相同的常量字符串去初始
//化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同，str3和str4相同。




//⼆维数组传参的本质
//void cq(int(*p)[5], int x, int y)
//{
//
//	for (int i = 0; i < x; i++)
//	{
//		for (int j = 0; j < y; j++)
//		{
//			printf("%d ",*(*(p+i)+j));
//		}
//		printf("\n");
//	}
//}
//int main()
//{
//
//	int arr[][5] = {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
//	cq(arr, 3, 5);
//	
//	
//}



//指针数组和数组指针的区别
//类型不同：指针数组是数组，其元素为指针；数组指针是指针，指向一个数组。
//用途不同：指针数组常用于存储多个指针，这些指针可以指向不同的数据类型或相同数据类型的不同实例；
//			数组指针则用于操作整个数组，如传递数组到函数时保持数组的大小信息。

//int main() 
//{
//	int arr[3] = { 1, 2, 3 };
//	int* arrPtr[3]; // 指针数组  
//	int(*ptr)[3];  // 数组指针  
//
//	// 初始化指针数组  
//	arrPtr[0] = &arr[0];
//	arrPtr[1] = &arr[1];
//	arrPtr[2] = &arr[2];
//
//	// 初始化数组指针  
//	ptr = &arr;
//
//	// 访问元素  
//	printf("%d\n", *arrPtr[0]); // 通过指针数组访问  
//	printf("%d\n", (*ptr)[1]);  // 通过数组指针访问  
//
//	return 0;
//}
//定义一个整型的3行3列二维数组，使用行指针对这个二维数组进行输入赋值，并且按照行进行打印数据
//int main()
//{
//	int a[3][3],i,j;
//	int(*p)[3] = a;
//	int r = sizeof(a) / sizeof(a[0]);
//	int c = sizeof(a[0]) / sizeof(a[0][0]);
//	for (i = 0; i < r; i++)
//	{
//		for (j = 0; j < c; j++)
//		{
//			scanf("%d",*(p+i)+j);
//		}
//	}
//	for (i = 0; i < r; i++)
//	{
//		for (j = 0; j < c; j++)
//		{
//			printf("%d ", *(*(p + i) + j));
//		}
//		printf("\n");
//	}


//}



//函数指针
//void test()
//{
//	printf("hehe\n");
//}
//int main()
//{
//	printf("test: %p\n", test);
//	printf("&test: %p\n", &test);
//	return 0;
//}
//总结：&函数名/函数名是函数的首地址
//函数指针变量的使用
//void Add(int x, int y)
//{
//	return x + y;
//}
//int main()
//{
//	int(*pf)(int, int) = Add;//指向类型看返回值类型
//	printf("%d",(*pf)(2,3));
//
//}
// 
// 
//分析下面的类型并尝试使用
//int  (*mm)(void (*f)(float b), int a, char* m);
//void f(float b)
//{
//	printf("%f\n",b);
//}
//int fuc(void (*f)(float b), int a, char* m)
//{
//	f(3.14);
//	printf("%d\n", a);
//	printf("%s\n", m);
//	return 1;
//}
//int main()
//{
//	int(*mm)(void (*f)(float b), int a, char* m);
//	mm = fuc;
//	int res = mm(f,30,"hello");
//	printf("%d",res);
//}

//int  *mm(void (*f)(float b), int a, char *m);
// 指针函数--返回一个指针，需要设置一个动态内存才能返回
//void f(float b)
//{
//	printf("%f\n", b);
//}
//int *mm(void (*f)(float b), int a, char* m)
//{
//	f(3.14);
//	printf("%d\n", a);
//	printf("%s\n", m);
//	int* p = (int*)malloc(4);
//	return p;
//}
//int main()
//{
//	int* p = mm(f,30,"hello");
//	*p = 40;
//	printf("%d", *p);
//}
//指针函数
//char* MyStrCat(char* str1, const char* str2)
//{
//	printf("str1,str2:%p %p\r\n", str1, str2);
//
//	// 拼接	
//	// 先找到str1的\0
//	int i = 0;
//	while (*(str1 + i) != '\0')
//	{
//		i++;
//	}
//	// 在找str2里面的字符放入到str1里面去
//	int j = 0;
//	while (*(str2 + j) != '\0')
//	{
//		*(str1 + i + j) = *(str2 + j);
//		j++;
//	}
//	// 最后补\0 
//	*(str1 + i + j) = '\0';
//
//	return str1;
//}
//
//int main(void)
//{
//	char s1[30] = "hello";
//	char s2[] = " world";
//
//	printf("s1,s2:%p %p\r\n", s1, s2);
//
//	char* p = MyStrCat(s1, s2);  // 0061FE82
//	printf("%s\r\n", p);
//	printf("%s\r\n", s1);
//	return 0;
//}
